using System.Diagnostics.Tracing;
using Identity.Application.Contracts.Common;
using Identity.Application.Contracts.Responses.Account;
using Identity.Application.Contracts.Services;
using Identity.Domain.Aggregates;
using Identity.Infrastructure.Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.WebUtilities;

namespace Identity.Infrastructure.Persistence.IdentityService;

public class UserService : IUserService
{
    private readonly UserManager<ApplicationUser> _userManager;

    public UserService(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;

    }

    public async Task<CreateUserResult> CreateUserAsync(Guid userId, string username, string email, string password)
    {

        var user = new ApplicationUser { Id = userId, UserName = username, Email = email, SecurityStamp = Guid.NewGuid().ToString() };
        var result = await _userManager.CreateAsync(user, password);
        if (!result.Succeeded)
            return CreateUserResult.Failed(result.Errors.Select(e => e.Description));

        return CreateUserResult.Success(user.Id);
    }

    public async Task<UserDto?> GetUserByIdAsync(Guid userId)
    {
        var user = await _userManager.FindByIdAsync(userId.ToString());
        if (user == null) return null;
        var roles = await _userManager.GetRolesAsync(user);
        return new UserDto(user.Id, user.UserName!, user.Email!, roles);
    }

    public async Task<UserDto?> GetUserByNameAsync(string userName)
    {
        var user = await _userManager.FindByNameAsync(userName);
        if (user == null) return null;
        var roles = await _userManager.GetRolesAsync(user);
        return new UserDto(user.Id, user.UserName!, user.Email!, roles);
    }

    public async Task<UserDto?> GetUserByEmailAsync(string email)
    {
        var user = await _userManager.FindByEmailAsync(email);
        if (user == null) return null;
        var roles = await _userManager.GetRolesAsync(user);
        return new UserDto(user.Id, user.UserName!, user.Email!, roles);
    }

    //认证邮件/token
    public async Task<string> GenerateEmailConfirmationTokenAsync(Guid userId)
    {
        var user = await _userManager.FindByIdAsync(userId.ToString());
        if (user == null) throw new KeyNotFoundException("User not found");
        return await _userManager.GenerateEmailConfirmationTokenAsync(user);
    }

    public async Task<bool> ConfirmEmailAsync(Guid userId, string token)
    {
        var decodedToken = System.Text.Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(token));
        var user = await _userManager.FindByIdAsync(userId.ToString());
        if (user == null) return false;
        var result = await _userManager.ConfirmEmailAsync(user, decodedToken);
        return result.Succeeded;
    }


    public async Task<string> GeneratePasswordResetTokenAsync(string email)
    {
        var user = await _userManager.FindByEmailAsync(email);
        if (user == null) throw new KeyNotFoundException("User not found");

        var resetToken = await _userManager.GeneratePasswordResetTokenAsync(user);
        return resetToken;
    }



    //密码操作
    public async Task<OperationResult> ChangePasswordAsync(Guid userId, string currentPassword, string newPassword)
    {
        var user = await _userManager.FindByIdAsync(userId.ToString());
        if (user == null) return OperationResult.Failed("User not found");
        var result = await _userManager.ChangePasswordAsync(user, currentPassword, newPassword);
        return result.Succeeded ? OperationResult.Success() : OperationResult.Failed(string.Join(",", result.Errors.Select(e => e.Description)));
    }
    public async Task<OperationResult> CheckPasswordAsync(Guid userId, string password)
    {
        var user = await _userManager.FindByIdAsync(userId.ToString());
        if (user == null) return OperationResult.Failed("User not found");
        var result = await _userManager.CheckPasswordAsync(user, password);
        return result ? OperationResult.Success() : OperationResult.Failed("密码不正确");
    }
    public async Task<OperationResult> ResetPasswordAsync(Guid userId, string token, string newPassword)
    {
        var user = await _userManager.FindByIdAsync(userId.ToString());
        if (user == null) return OperationResult.Failed("User not found");
        var result = await _userManager.ResetPasswordAsync(user, token, newPassword);
        return result.Succeeded ? OperationResult.Success() : OperationResult.Failed(string.Join(",", result.Errors.Select(e => e.Description)));
    }


    //检查用户合法性
    public async Task<bool> UserExistsByEmailAsync(string email)
    {
        var user = await _userManager.FindByEmailAsync(email);
        if (user == null) return false;

        return true;
    }
    public async Task<bool> UserExistsByUserNameAsync(string name)
    {
        var user = await _userManager.FindByNameAsync(name);
        if (user == null) return false;

        return true;
    }

    public async Task<bool> IsEmailConfirmedAsync(Guid userId)
    {
        var user = await _userManager.FindByIdAsync(userId.ToString());
        if (user == null) return false;
        return await _userManager.IsEmailConfirmedAsync(user);
    }

    public async Task<UserDto?> UpdateUserAsync(UserAggregate userAggregate)
    {

        var user = await _userManager.FindByIdAsync(userAggregate.Id.ToString());
        if (user == null) return null;

        user.Id = userAggregate.Id;
        user.UserName = userAggregate.UserName;
        user.Roles = userAggregate._roles;
        user.Email = userAggregate.Email;

        var result = await _userManager.UpdateAsync(user);
        if (!result.Succeeded) return null;
        return new UserDto(user.Id, user.UserName, user.Email, user.Roles);
    }
    
    public async Task<IList<UserAccountInfoDto>> GetAllUsersAsync()
    {
        var users = _userManager.Users.ToList();
        var userDtos = new List<UserAccountInfoDto>();
        foreach (var user in users)
        {
            var roles = await _userManager.GetRolesAsync(user);
            userDtos.Add(new UserAccountInfoDto(user.Id.ToString(), user.UserName!, user.Email!, roles, user.CreatedAt, user.EmailConfirmed));
        }
        return userDtos;
    }


}



